package rich_err

import "net/http"

type RichRespCode uint64

const (
	// Stub相当于占位符，可以用于任意情况
	Stub RichRespCode = 1 << iota
	OK
	IdentifierNotFound
	// Deprecated
	NotAllowed
	Confilct
	DriverFailed
	DatabaseFailed
	ResourceInsufficient
	ActionFailed
	RequestInvalid
	NotImplemented
	// Forbidden应当可以代替NotAllowed
	Forbidden
	Busy
)

var httpByCode = map[RichRespCode]int{
	Stub:               http.StatusInternalServerError,
	OK:                 http.StatusOK,
	IdentifierNotFound: http.StatusNotFound,
	// Deprecated
	NotAllowed:           http.StatusBadRequest,
	Confilct:             http.StatusConflict,
	DriverFailed:         http.StatusInternalServerError,
	DatabaseFailed:       http.StatusInternalServerError,
	ResourceInsufficient: http.StatusInternalServerError,
	ActionFailed:         http.StatusInternalServerError,
	RequestInvalid:       http.StatusBadRequest,
	NotImplemented:       http.StatusNotImplemented,
	Forbidden:            http.StatusForbidden,
	Busy:                 http.StatusTooManyRequests,
}

type RichError struct {
	// 值小于等于0时表示code无效
	code RichRespCode
	err  error
}

func NewError(code RichRespCode, err error) *RichError {
	return &RichError{
		code: code,
		err:  err,
	}
}

func NewLooseError(err error) *RichError {
	return &RichError{
		code: Stub,
		err:  err,
	}
}

func (e *RichError) Code() RichRespCode {
	return e.code
}

func (e *RichError) Error() error {
	return e.err
}

func (e *RichError) SetError(err error) *RichError {
	e.err = err
	return e
}

func (e *RichError) SetCode(code RichRespCode) *RichError {
	e.code = code
	return e
}

func (e *RichError) String() string {
	return e.err.Error()
}

// HTTP returns the related HTTP status code and error as body
func (e *RichError) HTTP() (int, error) {
	return httpByCode[e.code], e.err
}
